﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Linq;
using System.Windows.Forms;
using ChatClientApp.Tools;
using System.IO;
using ChatClientApp.Classes;
using ChatServerApp.Classes;

namespace ChatClientApp.GUI
{
    public partial class fContactList : Form
    {
        public static DelegateLogEntry dle;
        public delegate void DelegateLogEntry(String value);
        ListeningServer server;
        User_Complete activeUser;
        List<ChatMessage> starredOnMessage;
        List<ChatFileMessage> starredOnFileMessage;
        BackgroundWorker starredOnMessageBW;
        public delegate void DelegateStartChat(ChatMessage msg);
        public delegate void DelegateRequestChatPartners(List<string> p);
        public delegate void DelegateClearContactList();
        public delegate void DelegateShowMessage();
        public delegate void DelegateShowFileMessage();
        private Brush[] myBrush;
        fContactSearch search = null;
        fContactDelete del = null;

        public fContactList()
        {
            InitializeComponent();
            // ChatClient.ClientClass.OnSendMessageHandler += new ChatClient.ClientClass.SendMessageEventHandler(client_OnSendMessageHandler);
            starredOnMessage = new List<ChatMessage>();
            starredOnFileMessage = new List<ChatFileMessage>();
            starredOnMessageBW = new BackgroundWorker();
            starredOnMessageBW.WorkerSupportsCancellation = true;
        }

        private void CCA_ContactList_Load(object sender, EventArgs e)
        {
            try
            {
                this.Hide();
                fLogin form_cl = new fLogin();
                this.listBox1.DrawMode = DrawMode.OwnerDrawFixed;
                this.listBox1.DrawItem += listBox1_DrawItem;
                startListeningServer();

                if (form_cl.ShowDialog() == DialogResult.OK)
                {
                    this.Text = ActiveComponents.ActiveUser.Nick;
                    ListeningServer.OnReceivedMessageHandler += new ListeningServer.ReceivedMessageEventHandler(ListeningServer_OnReceivedMessageHandler);
                    ListeningServer.OnReceivedFileMessageHandler += new ListeningServer.ReceivedFileMessageEventHandler(ListeningServer_OnReceivedFileMessageHandler);
                    this.Show();
                    form_cl.Dispose();
                    this.activeUser = ActiveComponents.ActiveUser;
                    addLogEntry("Logged in as: " + activeUser.Nick);
                    requestChatPartners(activeUser.Contacts);
                    starredOnMessageBW.DoWork += new DoWorkEventHandler(starredOnMessageBW_DoWork);
                    starredOnMessageBW.RunWorkerAsync();
                }
                else if (form_cl.DialogResult == DialogResult.Retry)
                {
                    addLogEntry("Could not connect as: " + form_cl.getTriedNick());
                    this.CCA_ContactList_Load(sender, e);
                }
                else
                {
                    this.Dispose();
                }
            }
            catch (Exception ex)
            {
                System.Windows.Forms.MessageBox.Show("Probably user_complete.dll is missing.\r\n" + ex.Message, "Error");
            }

        }

        private void requestChatPartners(List<string> p)
        {
            string[,] contactsOnline = ServerHandling.ContactsOnline(p);
            fillContactList(contactsOnline);
        }

        private void fillContactList(string[,] p)
        {
            clearContactList();
            listBox1.ClearSelected();
            myBrush = new Brush[p.GetLength(0)];
            for (int i = 0; i < p.GetLength(0); i++)
            {
                if (p[i, 1] == "True")
                {
                    myBrush[i] = Brushes.Green;
                }
                else
                {
                    myBrush[i] = Brushes.Red;
                }
                listBox1.Items.Add(p[i,0]);
            }
        }

        private void clearContactList()
        {
            if (InvokeRequired)
            {
                Invoke(new DelegateClearContactList(clearContactList));
            }
            else
            {
                listBox1.Items.Clear();
            }
        }

        private bool startListeningServer()
        {
            while (true)
            {
                try
                {
                    server = new ListeningServer(ActiveComponents.ActiveServerPort);
                    ActiveComponents.ListenServer = server;
                    return true;
                }
                catch (Exception ex)
                {
                    if (!(ex.Message == "PORT USED"))
                    {
                        MessageBox.Show("Could not start Listening Server. You can't get Messages");
                        break;
                    }
                    else
                    {
                        ActiveComponents.ActiveServerPort++;
                    }
                }
            }
            return false;

        }

        private void CCA_ContactList_FormClosing(object sender, FormClosingEventArgs e)
        {
            try
            {
                starredOnMessageBW.CancelAsync();
                this.listBox1.DrawItem -= listBox1_DrawItem; 
                if (activeUser != null && activeUser.IsOnline)
                {
                    ListeningServer.OnReceivedMessageHandler -= new ListeningServer.ReceivedMessageEventHandler(ListeningServer_OnReceivedMessageHandler);
                    // ChatClient.ClientClass.OnSendMessageHandler -= new ChatClient.ClientClass.SendMessageEventHandler(client_OnSendMessageHandler);
                    ServerHandling.Logout(activeUser.Nick);
                    starredOnMessageBW.Dispose();
                    starredOnMessageBW.DoWork -= new DoWorkEventHandler(starredOnMessageBW_DoWork);
                }
            }
            catch (Exception ex)
            {
                File.WriteAllText("error.log", ex.Message);
                Application.Exit();
            }

        }

        private void client_OnSendMessageHandler(object sender, MessageEventArgs e)
        {
            this.addLogEntry(e.Message);
        }

        private void starredOnMessageBW_DoWork(object sender, DoWorkEventArgs e)
        {
            DateTime lastchecked = DateTime.Now;
            while (! starredOnMessageBW.CancellationPending)
            {
                if (lastchecked.AddSeconds(10) < DateTime.Now)
                {
                    int contacts = ServerHandling.GetContactCount(ActiveComponents.ActiveUser.Nick);
                    if (contacts != ActiveComponents.ActiveUser.Contacts.Count)
                        ActiveComponents.ActiveUser.Contacts = ServerHandling.GetContacts(ActiveComponents.ActiveUser.Nick);

                    InvokeRequestChatPartners(ActiveComponents.ActiveUser.Contacts);
                    lastchecked = DateTime.Now;
                }

                if (starredOnMessage.Count != 0)
                {
                    showMessage();
                }
                if (starredOnFileMessage.Count != 0)
                {
                    showFileMessage();
                }

                System.Threading.Thread.Sleep(1000);
            }
        }

        private void showMessage()
        {
            if (!InvokeRequired)
            {
                ChatMessage msg = starredOnMessage.ElementAt(0);
                starredOnMessage.RemoveAt(0);

                if (ActiveComponents.ActiveContactChat.Contains(msg.Nickname))
                {
                    fChatWindow current = ActiveComponents.ActiveContactChatWindow.Find(
                        delegate(fChatWindow cw)
                        {
                            return cw.Text == msg.Nickname;
                        }
                    );

                    current.Show();

                    if (current != null)
                    {
                        current.BringToFront();
                        current.AddMessage(msg.Message, msg.Ip);
                    }
                    else
                    {
                        fChatWindow temp = new fChatWindow();
                        temp.Text = msg.Nickname;
                        temp.Show();
                    }
                }
                else
                {
                    if (ActiveComponents.ActiveContactChat.Contains(msg.Nickname))
                    {
                        fChatWindow current = ActiveComponents.ActiveContactChatWindow.Find(
                            delegate(fChatWindow cw)
                            {
                                return cw.Text == msg.Nickname;
                            }
                        );

                        if (current != null)
                        {
                            current.BringToFront();
                            current.AddMessage(msg.Message, msg.Ip);
                        }
                    }
                }
            }
            else
            {
                Invoke(new DelegateShowMessage(showMessage));
            }
        }

        private void showFileMessage()
        {
            if (!InvokeRequired)
            {
                ChatFileMessage msg = starredOnFileMessage.ElementAt(0);
                starredOnFileMessage.RemoveAt(0);

                if (ActiveComponents.ActiveContactChat.Contains(msg.Nickname))
                {
                    fChatWindow current = ActiveComponents.ActiveContactChatWindow.Find(
                        delegate(fChatWindow cw)
                        {
                            return cw.Text == msg.Nickname;
                        }
                    );

                    current.Show();

                    if (current != null)
                    {
                        current.BringToFront();
                        current.AddFileMessage(msg);
                    }
                    else
                    {
                        fChatWindow temp = new fChatWindow();
                        temp.Text = msg.Nickname;
                        temp.Show();
                    }
                }
                else
                {
                    if (ActiveComponents.ActiveContactChat.Contains(msg.Nickname))
                    {
                        fChatWindow current = ActiveComponents.ActiveContactChatWindow.Find(
                            delegate(fChatWindow cw)
                            {
                                return cw.Text == msg.Nickname;
                            }
                        );

                        if (current != null)
                        {
                            current.BringToFront();
                            current.AddFileMessage(msg);
                        }
                    }
                }
            }
            else
            {
                Invoke(new DelegateShowFileMessage(showFileMessage));
            }
        }

        private void startChatWindow(ChatMessage msg)
        {
            fChatWindow test = new fChatWindow();
            test.Text = msg.Nickname;
            test.Show();
        }

        private void listBox1_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            if (listBox1.SelectedItem == null)
                return;

            String contactName = listBox1.SelectedItem.ToString();
            if (!checkActiveComponents(contactName))
            {
                fChatWindow test = new fChatWindow();
                test.Text = contactName;
                test.Show();
            }
            else
            {
                fChatWindow current = ActiveComponents.ActiveContactChatWindow.Find(
                    delegate(fChatWindow cw)
                    {
                        return cw.Text == contactName;
                    }
                );
                if (current != null)
                    current.BringToFront();
            }
        }

        private bool checkActiveComponents(String contactName)
        {
            return ActiveComponents.ActiveContactChat.Contains(contactName);
        }

        private void listBox1_DrawItem(object sender, DrawItemEventArgs e)
        {
            try
            {
                if (! (e.Index == -1))
                {
                    Color fore = e.ForeColor;
                    e.DrawBackground();
                    e.Graphics.DrawString(((ListBox)sender).Items[e.Index].ToString(), e.Font, myBrush[e.Index], e.Bounds, StringFormat.GenericDefault);
                    e.DrawFocusRectangle();
                }
            }
            catch (Exception ex)
            {
                ex.ToString();
            }
        }

        private void InvokeRequestChatPartners(List<string> p)
        {
            if (InvokeRequired)
            {
                Invoke(new DelegateRequestChatPartners(requestChatPartners), new object[] { p });

            }
            else
            {
                requestChatPartners(p);
            }
        }

        public void addLogEntry(String text)
        {
            DateTime dt = DateTime.Now;
            text = dt.Year + "/" + dt.Month + "/" + dt.Day + " " + dt.TimeOfDay.Hours + ":" + dt.TimeOfDay.Minutes + " : " + text;

            if (File.Exists("log.txt"))
                File.AppendAllText("log.txt", text + Tools.Tools.NL);
            else
                File.WriteAllText("log.txt", text + Tools.Tools.NL);
        }

        private void ListeningServer_OnReceivedMessageHandler(object sender, ChatMessage msg)
        {
            if (ActiveComponents.ActiveContactChat.Contains(msg.Nickname))
            {
                this.starredOnMessage.Add(msg);
            }
            else if (InvokeRequired)
            {
                Invoke(new DelegateStartChat(startChatWindow), new object[] { msg });
                this.starredOnMessage.Add(msg);
            }
            else
            {
                ;
            }
        }

        private void ListeningServer_OnReceivedFileMessageHandler(object sender, ChatFileMessage fMsg)
        {
            if (ActiveComponents.ActiveContactChat.Contains(fMsg.Nickname))
            {
                this.starredOnFileMessage.Add(fMsg);
            }
            else if (InvokeRequired)
            {
                Invoke(new DelegateStartChat(startChatWindow), new object[] { (ChatMessage)fMsg });
                this.starredOnFileMessage.Add(fMsg);
            }
            else
            {
                ;
            }
        }

        private void logoutToolStripMenuItem_Click(object sender, EventArgs e)
        {
            CCA_ContactList_FormClosing(sender, new FormClosingEventArgs(CloseReason.UserClosing, false));
            this.CCA_ContactList_Load(sender, e);
        }

        private void hinzufügenToolStripMenuItem_Click(object sender, EventArgs e)
        {
            search = new fContactSearch();
            search.Show();
            search.Disposed +=new EventHandler(search_Disposed);
        }

        private void search_Disposed(object sender, EventArgs e)
        {
            requestChatPartners(Tools.ActiveComponents.ActiveUser.Contacts);
            search.Disposed -= new EventHandler(search_Disposed);
            search = null;
            //TODO: stop hier            
        }

        private void entfernenToolStripMenuItem_Click(object sender, EventArgs e)
        {
            del = new fContactDelete();
            del.Show();
            del.Disposed += new EventHandler(del_Disposed);
        }

        private void del_Disposed(object sender, EventArgs e)
        {
            requestChatPartners(Tools.ActiveComponents.ActiveUser.Contacts);
            del.Disposed -= new EventHandler(del_Disposed);
            del = null;
            //TODO: stop hier            
        }

    }
}
